package com.zenglx.multilanguage.metadata;


import cn.hutool.core.bean.BeanUtil;
import com.baomidou.mybatisplus.annotation.TableId;
import com.baomidou.mybatisplus.core.config.GlobalConfig;
import com.baomidou.mybatisplus.core.metadata.TableFieldInfo;
import com.baomidou.mybatisplus.core.metadata.TableInfo;
import com.baomidou.mybatisplus.core.metadata.TableInfoHelper;
import com.baomidou.mybatisplus.core.toolkit.GlobalConfigUtils;
import com.zenglx.multilanguage.annotation.MultiLanguage;
import com.zenglx.multilanguage.annotation.MultiLanguageField;
import lombok.extern.slf4j.Slf4j;
import org.apache.ibatis.builder.MapperBuilderAssistant;
import org.apache.ibatis.reflection.Reflector;
import org.apache.ibatis.reflection.ReflectorFactory;
import org.apache.ibatis.session.Configuration;

import java.lang.reflect.Field;
import java.util.*;
import java.util.concurrent.ConcurrentHashMap;

/**
 * <p>
 * 实体类反射表辅助类
 * </p>
 *
 * @author liangxi.zeng
 * @since 2024-05-15
 */
@Slf4j
public class ZlxTableInfoHelper {


    private static final Map<Class<?>, ZlxTableInfo> modelClassTableMap = new ConcurrentHashMap<>();

    private static final Map<String, ZlxTableInfo> mapperClassTableMap = new ConcurrentHashMap<>();
    /**
     * <p>
     * 实体类反射获取表信息【初始化】
     * </p>
     *
     * @param modelClass 反射实体类
     * @param mapName map
     * @return 数据库表反射信息
     */
    public synchronized static ZlxTableInfo initTableInfo(MapperBuilderAssistant builderAssistant, Class<?> modelClass, String mapName) {
        ZlxTableInfo zlxTableInfo = new ZlxTableInfo(modelClass);
        TableInfo tableInfo = TableInfoHelper.initTableInfo(builderAssistant, modelClass);

        Configuration configuration = tableInfo.getConfiguration();
        GlobalConfig globalConfig = GlobalConfigUtils.getGlobalConfig(configuration);
        GlobalConfig.DbConfig dbConfig = globalConfig.getDbConfig();
        ReflectorFactory reflectorFactory = tableInfo.getConfiguration().getReflectorFactory();
        Reflector reflector = reflectorFactory.findForClass(modelClass);
        List<Field> list = TableInfoHelper.getAllFields(modelClass);
        for (Field field : list) {
            TableId tableId = field.getAnnotation(TableId.class);
            if (tableId != null) {
                TableFieldInfo primaryKey = new TableFieldInfo(dbConfig, tableInfo, field, reflector, false);
                zlxTableInfo.getEntityClassPkColumns().add(primaryKey);
                zlxTableInfo.getEntityClassColumns().add(primaryKey);
                break;
            }
        }

        BeanUtil.copyProperties(tableInfo, zlxTableInfo);
        //多语言表
        if (modelClass.isAnnotationPresent(MultiLanguage.class)) {
            zlxTableInfo.setMultiLanguage(true);
        }
        //多语言字段
        zlxTableInfo.setMultiLanguageColumns(new HashSet<>());
        List<TableFieldInfo> fieldList = tableInfo.getFieldList();
        for (TableFieldInfo tableFieldInfo : fieldList) {
            Field field = tableFieldInfo.getField();
            if (field.isAnnotationPresent(MultiLanguageField.class)) {
                zlxTableInfo.getMultiLanguageColumns().add(tableFieldInfo);
            }
            zlxTableInfo.getEntityClassColumns().add(tableFieldInfo);
        }
        modelClassTableMap.put(modelClass,zlxTableInfo);
        mapperClassTableMap.put(mapName, zlxTableInfo);

        return zlxTableInfo;
    }


    /**
     * 获取表对象
     *
     * @param mapperClass mapperClass
     * @return EntityTable
     */
    public static ZlxTableInfo getTableByMapper(String mapperClass) {
        ZlxTableInfo entityTable = mapperClassTableMap.get("interface "+mapperClass);
        if (entityTable == null) {
            log.debug("not found table for mapper class: " + mapperClass);
        }
        return entityTable;
    }

    /**
     * <p>
     * 获取实体映射表信息
     * </p>
     *
     * @param modelClass 反射实体类
     * @return 数据库表反射信息
     */
    public static ZlxTableInfo getTableInfo(Class<?> modelClass) {
        ZlxTableInfo zlxTableInfo = modelClassTableMap.get(modelClass);
        return zlxTableInfo;
    }



}
